import os
import cv2
import sys
import shutil
from tkinter import *
import tkinter.filedialog as fd
from tkinter import messagebox
from PIL import Image
import numpy as np

def getImageAndLabels(path):
    facesSamples=[]
    ids=[]
    i = 1
    imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
    #检测人脸
    face_detector = cv2.CascadeClassifier('D:/haarcascade_frontalface_default.xml')
    #遍历列表中的图片
    for imagePath in imagePaths:
        #打开图片
        PIL_img=Image.open(imagePath).convert('L')
        #将图像转换为数组
        img_numpy=np.array(PIL_img,'uint8')
        faces = face_detector.detectMultiScale(img_numpy)
        #获取每张图片的id
        id= i #int(os.path.split(imagePath)[1].split('.')[0])
        for x,y,w,h in faces:
            facesSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)
        os.makedirs(os.path.join(path3, str(id)))
        i=i+1
    return facesSamples,ids

def openFloder1():
    folder_path = fd.askdirectory()  # 打开文件
    show_folderPath1.delete(0, END)  # 清空
    show_folderPath1.insert(0, folder_path)  # 写入路径
    facesSamples, ids = getImageAndLabels(folder_path)
    # 获取训练对象
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.train(facesSamples, np.array(ids))
    recognizer.write('D:/trainerdata/trainer.yml')


def openFloder2():
    tids = []
    path2 = fd.askdirectory()  # 打开文件
    show_folderPath2.delete(0, END)  # 清空
    show_folderPath2.insert(0, path2)  # 写入路径
    recognizer = cv2.face.LBPHFaceRecognizer_create()
    recognizer.read('D:/trainerdata/trainer.yml')
    imagePaths = [os.path.join(path2, f) for f in os.listdir(path2)]
    for imagePath in imagePaths:
        print(imagePath)
        img = cv2.imread(imagePath)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        face_detector = cv2.CascadeClassifier('D:/haarcascade_frontalface_default.xml')
        faces = face_detector.detectMultiScale(gray)
        for x, y, w, h in faces:
            # 人脸识别
            tid, confidence = recognizer.predict(gray[y:y + h, x:x + w])
        print(imagePath,tid,confidence)
        for j in os.listdir(path3):
           if int(tid)== int(os.listdir(path3)[int(j)-1]) and confidence<110:
                shutil.copy(imagePath, os.path.join(path3, str(j)))

def openFloder3():
    global path3
    path3= fd.askdirectory()  # 打开文件
    show_folderPath3.delete(0, END)  # 清空
    show_folderPath3.insert(0, path3)  # 写入路径

def start():
    messagebox.showinfo('提示', f'分类后的照片已保存到\n{path3}')

top = Tk()
top.title('OpenCV分类')  # 窗口标题
top.geometry('500x400')  # 窗口大小

show_folderPath1 = Entry(top)
show_folderPath1.grid(row=4, column=2,ipadx=30,padx=15,pady=10)
show_folderPath2 = Entry(top)
show_folderPath2.grid(row=6, column=2,ipadx=30,padx=15,pady=10)
show_folderPath3 = Entry(top)
show_folderPath3.grid(row=2, column=2,ipadx=30,padx=15,pady=10)
hdr3 = Label(top,text="请选择分类结果输出文件夹", font=("微软雅黑", 11)).grid(row=1, column=2,pady=5)
hdr2 = Label(top,text="请选择待分类人像照片所在的文件夹", font=("微软雅黑", 11)).grid(row=5, column=2,pady=5)
hdr1 = Label(top,text="请选择人像照片训练集文件夹", font=("微软雅黑", 11)).grid(row=3, column=2,pady=5)
btn1 = Button(top, text="浏览", command=openFloder1)  # 设置一个按钮
btn2 = Button(top, text="浏览", command=openFloder2)  # 设置一个按钮
btn3 = Button(top, text="浏览", command=openFloder3)  # 设置一个按钮
btn4 = Button(top, text="开始分类", command=start)  # 设置一个按钮
btn1.grid(row=4, column=3,ipadx=15,pady=10)
btn2.grid(row=6, column=3,ipadx=15,pady=10)
btn3.grid(row=2, column=3,ipadx=15,pady=10)
btn4.grid(row=7, column=2,ipadx=20,pady=20,ipady=5)
top.mainloop()






